package cn.study.synchronizedTest;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jol.info.ClassLayout;

/**
 * @Author     ：跟大佳一起学架构
 * @Description：
 * 测试 轻量级锁，重量级锁标记变化
 * 无锁 001
 * 偏向锁 101
 * 轻量级锁 00
 * 重量级锁 10
 */
@Slf4j
public class LockLightDemo {

    public static void lightLock() throws InterruptedException {
        //HotSpot 虚拟机在启动后有个 4s 的延迟才会对每个新建的对象开启偏向锁模式
        Thread.sleep(4000);
        Object obj = new Object();
        log.debug(ClassLayout.parseInstance(obj).toPrintable());

        new Thread(new Runnable() {
            @Override
            public void run() {
                log.debug(Thread.currentThread().getName()+"开始执行。。。\n"
                        +ClassLayout.parseInstance(obj).toPrintable());
                synchronized (obj){
                    // 思考：偏向锁执行过程中，调用hashcode会发生什么？
                    //obj.hashCode();
//                    //obj.notify();
////                    try {
////                        obj.wait(50);
////                    } catch (InterruptedException e) {
////                        e.printStackTrace();
////                    }

                    log.debug(Thread.currentThread().getName()+"获取锁执行中。。。\n"
                            +ClassLayout.parseInstance(obj).toPrintable());

                    new StringBuffer().append("跟大佳一起学架构").append("大佳");
                }
                log.debug(Thread.currentThread().getName()+"释放锁。。。\n"
                        +ClassLayout.parseInstance(obj).toPrintable());
            }
        },"thread1").start();

        // todo: 控制线程竞争时机
        // 个人演示的时候会出现这几种情况：
        // 1、T1开始(匿名偏向)->T1加锁(偏向)->T2开始(偏向)->T2加锁(轻量)->T1释放(偏向)->T2释放(无锁)
        // 2、T1开始(匿名偏向)->T2开始(匿名偏向)->T1加锁(偏向)->T2加锁(重量)->T1释放(重量)->T2释放(无锁或者重量)
        // 3、T1开始(匿名偏向)->T1加锁(偏向)->T2开始(偏向)->T1释放(偏向)->T2加锁(轻量)->T2释放(无锁或者轻量)
//        Thread.sleep(1);

        new Thread(new Runnable() {
            @Override
            public void run() {
                log.debug(Thread.currentThread().getName()+"开始执行。。。\n"
                        +ClassLayout.parseInstance(obj).toPrintable());
                synchronized (obj){

                    log.debug(Thread.currentThread().getName()+"获取锁执行中。。。\n"
                            +ClassLayout.parseInstance(obj).toPrintable());
                }
                log.debug(Thread.currentThread().getName()+"释放锁。。。\n"
                        +ClassLayout.parseInstance(obj).toPrintable());
            }
        },"thread2").start();

        Thread.sleep(5000);
        log.debug(ClassLayout.parseInstance(obj).toPrintable());
    }

    public static void main(String[] args) throws InterruptedException {
        lightLock();
//
//        Object obj = new Object();
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                log.debug(Thread.currentThread().getName()+"开始执行。。。\n"
//                        +ClassLayout.parseInstance(obj).toPrintable());
//                synchronized (obj){
//
//                    log.debug(Thread.currentThread().getName()+"获取锁执行中。。。\n"
//                            +ClassLayout.parseInstance(obj).toPrintable());
//                }
//                try {
//                    Thread.sleep(2000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                log.debug(Thread.currentThread().getName()+"释放锁。。。\n"
//                        +ClassLayout.parseInstance(obj).toPrintable());
//            }
//        },"thread3").start();

    }
}